package com.sl.biz.modular.views.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Maps;
import com.sl.biz.modular.views.dao.domain.entity.ViewConfigDO;
import com.sl.biz.modular.views.dao.service.ViewConfigDaoService;
import com.sl.biz.modular.views.service.ViewConfigBizService;
import com.sl.sys.ext.SysMenuExtension;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ViewConfigBizServiceImpl implements ViewConfigBizService, SysMenuExtension {
    private final ViewConfigDaoService viewConfigDaoService;

    @Override
    public List<ViewConfigDO> list(ViewConfigDO viewConfigDO) {
        LambdaQueryWrapper<ViewConfigDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(viewConfigDO.getGroupId()), ViewConfigDO::getGroupId, viewConfigDO.getGroupId());
        queryWrapper.eq(StrUtil.isNotBlank(viewConfigDO.getProductId()), ViewConfigDO::getProductId, viewConfigDO.getProductId());
        queryWrapper.eq(StrUtil.isNotBlank(viewConfigDO.getPublishFlag()), ViewConfigDO::getPublishFlag, viewConfigDO.getPublishFlag());
        List<ViewConfigDO> list = viewConfigDaoService.list(queryWrapper);
        return list;
    }


    @Override
    public Boolean removeById(ViewConfigDO viewConfigDO) {
        return viewConfigDaoService.removeById(viewConfigDO.getId());
    }

    @Override
    public String save(ViewConfigDO viewConfigDO) {
        viewConfigDO.setComponentUrl(viewConfigDO.getRouteUrl());
        if (StrUtil.isBlank(viewConfigDO.getId())) {
            viewConfigDO.setPublishFlag("OFFLINE");
        }
         viewConfigDaoService.saveOrUpdate(viewConfigDO);
        return viewConfigDO.getId();
    }

    @Override
    public ViewConfigDO getById(ViewConfigDO viewConfigDO) {
        return viewConfigDaoService.getById(viewConfigDO.getId());
    }

    @Override
    public Boolean saveViewContent(ViewConfigDO processComp) {
        LambdaUpdateWrapper<ViewConfigDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(ViewConfigDO::getViewContent, processComp.getViewContent());
        lambdaUpdateWrapper.eq(ViewConfigDO::getId, processComp.getId());
        return viewConfigDaoService.update(lambdaUpdateWrapper);
    }

    @Override
    public Boolean offline(ViewConfigDO processComp) {
        LambdaUpdateWrapper<ViewConfigDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(ViewConfigDO::getPublishFlag, "OFFLINE");
        lambdaUpdateWrapper.eq(ViewConfigDO::getId, processComp.getId());
        return viewConfigDaoService.update(lambdaUpdateWrapper);
    }

    @Override
    public Boolean online(ViewConfigDO processComp) {
        LambdaUpdateWrapper<ViewConfigDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(ViewConfigDO::getPublishFlag, "ONLINE");
        lambdaUpdateWrapper.eq(ViewConfigDO::getId, processComp.getId());
        return viewConfigDaoService.update(lambdaUpdateWrapper);
    }

    @Override
    public ViewConfigDO getByPath(ViewConfigDO viewConfigDO) {
        LambdaQueryWrapper<ViewConfigDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(viewConfigDO.getRouteUrl()), ViewConfigDO::getRouteUrl, viewConfigDO.getRouteUrl());
        List<ViewConfigDO> list = viewConfigDaoService.list(queryWrapper);
        return CollUtil.get(list, 0);
    }

    @Override
    public List<Tree<String>> buildOtherMenuTree(List<Tree<String>> build) {
        ViewConfigDO viewConfigDO = new ViewConfigDO();
        viewConfigDO.setPublishFlag("ONLINE");
        List<ViewConfigDO> list = this.list(viewConfigDO);
        if (CollUtil.isEmpty(list)) {
            return build;
        }
        Map<String, List<ViewConfigDO>> viewConfigMap = list.stream().collect(Collectors.groupingBy(v -> {
            return StrUtil.nullToDefault(v.getParentId(), StrUtil.EMPTY);
        }));

        expenseTreeAndInject(build, viewConfigMap);
        return build;
    }

    private void expenseTreeAndInject(List<Tree<String>> build, Map<String, List<ViewConfigDO>> viewConfigMap) {
        if (CollUtil.isEmpty(build)) {
            return;
        }
        for (Tree<String> stringTree : build) {

            List<Tree<String>> children = stringTree.getChildren();
            expenseTreeAndInject(children, viewConfigMap);
            String id = stringTree.getId();
            List<ViewConfigDO> viewConfigDOS = viewConfigMap.get(id);
            if (CollUtil.isNotEmpty(viewConfigDOS)) {
                List<Tree<String>> collect = viewConfigDOS.stream().map(v -> {
                    Tree<String> tree = new Tree<>();
                    tree.setId(v.getId());
                    tree.setName(v.getViewName());
                    tree.setParentId(v.getParentId());
                    tree.setWeight(1);
                    tree.put("title", v.getViewName());
                    tree.put("code", v.getViewCode());
                    tree.put("category", "MENU");
                    tree.put("module", "1548901111999770525");
                    tree.put("menuType", "MENU");
                    tree.put("path", "/views" + v.getRouteUrl());
                    tree.put("component", "lowcode/engine");
                    tree.put("visible", "TRUE");
                    tree.put("icon", v.getIcon());
                    tree.put("color", "#05a045");
                    tree.put("sortCode", 1);
                    tree.put("deleted", 0);
                    Map<String, Object> map = Maps.newHashMap();
                    map.put("icon", v.getIcon());
                    map.put("type", "menu");
                    map.put("hidden", false);
//                    map.put("preview", true);
                    map.put("viewFlag", true);
                    map.put("title", v.getViewName());
                    tree.put("meta", map);
                    tree.put("children", null);
                    return tree;
                }).toList();

                for (Tree<String> tree : collect) {
                    stringTree.addChildren(tree);
                }
            }
        }
    }
}
